#pragma once

#include "idpool.h"

class TestIdPool
{
	class MyIdPool
	: public IdPool < MyIdPool >
	{
	public:
		MyIdPool ( int maxId )
		: IdPool < MyIdPool > ( maxId )
		{
		}
	};
	
	static void TestCreateSingleId ()
	{
		MyIdPool pool ( 100 );
		MyIdPool::Id id = pool.CreateNewId ();
		assert ( pool.HasId ( id ) );
	}
	
	static void TestHasNullId ()
	{
		MyIdPool pool ( 100 );
		MyIdPool::Id id;
		assert ( ! pool.HasId ( id ) );
		pool.CreateNewId ();
		pool.CreateNewId ();
		pool.CreateNewId ();
		assert ( ! pool.HasId ( id ) );
	}

	static void TestDeleteSingleId ()
	{
		MyIdPool pool ( 100 );
		MyIdPool::Id id = pool.CreateNewId ();
		pool.DeleteId ( id );
		assert ( ! pool.HasId ( id ) );
	}
	
	static void TestMultipleDeleteSameId ()
	{
		MyIdPool pool ( 100 );
		MyIdPool::Id id = pool.CreateNewId ();
		pool.DeleteId ( id );
		pool.DeleteId ( id );
		pool.DeleteId ( id );
		assert ( ! pool.HasId ( id ) );
	}
	
	static void TestDeleteNullId ()
	{
		bool exception = false;
		MyIdPool pool ( 100 );
		MyIdPool::Id id;
		try
		{
			pool.DeleteId ( id );
		}
		catch ( DeleteNullIdException )
		{
			exception = true;
		}
		assert ( exception == true );
	}
	
	static void TestPoolOverflow ()
	{
		bool exception = false;
		MyIdPool pool ( 100 );
		for ( int i = 0; i < 100; i++ )
			pool.CreateNewId ();
		try
		{
			pool.CreateNewId ();
		}
		catch ( IdPoolOverflowException )
		{
			exception = true;
		}
		assert ( exception );
	}
	
	static void TestReturnDeletedIdsToPool ()
	{
		MyIdPool pool ( 100 );
		for ( int i = 0; i < 1000; i++ )
		{
			MyIdPool::Id id = pool.CreateNewId ();
			pool.DeleteId ( id );
		}
	}
	
public:
	static void Run ()
	{
		TestCreateSingleId ();
		TestHasNullId ();
		TestDeleteSingleId ();
		TestMultipleDeleteSameId ();
		TestDeleteNullId ();
		TestPoolOverflow ();
		TestReturnDeletedIdsToPool ();
	}
};
